package uc

import (
	"context"
	"go.uber.org/zap"
	"google.golang.org/protobuf/proto"
	"strconv"
	"strings"
	"time"
	"wzgames/internal/constant"
	"wzgames/internal/gloader"
	"wzgames/internal/model/dwp"
	"wzgames/pkg/logger"
)

type DouWalletService struct {
}

func NewDouWalletService() *DouWalletService {
	return &DouWalletService{}
}

// Balance 查询玩家钱包余额
func (w *DouWalletService) Balance(ctx context.Context, req *dwp.BalanceAuthReply, res *dwp.BalanceReply) error {
	code, data := WalletMgr().Balance(req)
	res.Code = int32(code)
	res.Data = data
	return nil
}

// Deposit 钱包转入
func (w *DouWalletService) Deposit(ctx context.Context, req *dwp.DepWitAuthReply, res *dwp.DepWitReply) error {
	code, data := WalletMgr().Deposit(req)
	res.Code = int32(code)
	res.Data = data
	if code == 0 {
		w.sendBalanceChange(req.AgtID, req.Uid, req.CurrID)
	}
	return nil
}

// Withdraw 钱包转出
func (w *DouWalletService) Withdraw(ctx context.Context, req *dwp.DepWitAuthReply, res *dwp.DepWitReply) error {
	code, data := WalletMgr().Withdraw(req)
	res.Code = int32(code)
	res.Data = data
	if code == 0 {
		w.sendBalanceChange(req.AgtID, req.Uid, req.CurrID)
	}
	return nil
}

// CheckTransfer 查询转账状态
func (w *DouWalletService) CheckTransfer(ctx context.Context, req *dwp.DwCheck, res *dwp.DepWitReply) error {
	code, data := WalletMgr().CheckTransfer(req)
	res.Code = int32(code)
	res.Data = data
	return nil
}

func uidKey(uid uint64) string {
	var bd strings.Builder
	bd.WriteString(gloader.EnvString())
	bd.WriteString(constant.CacheUidToToken)
	bd.WriteString(strconv.FormatUint(uid, 10))

	return bd.String()
}

func (w *DouWalletService) sendBalanceChange(agtId int64, uid uint64, currId int32) {
	uTokenKey := uidKey(uid)
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
	ret, e := gloader.CommMgr().RedisPool().Get().HGetAll(ctx, uTokenKey).Result()
	cancel()
	if e != nil {
		logger.Error("[UC] send balance change fail on redis.HGetAll", zap.Int64("AgtId", agtId), zap.Uint64("Uid", uid), zap.Int32("CurrId", currId), zap.Error(e))
		return
	}
	if ret == nil {
		return
	}

	obj := &dwp.BalanceChange{
		AgtID:  agtId,
		Uid:    uid,
		CurrId: currId,
	}
	b, err := proto.Marshal(obj)
	if err != nil {
		logger.Error("[UC] send balance change fail on proto.Marshal", zap.Int64("AgtId", agtId), zap.Uint64("Uid", uid), zap.Int32("CurrId", currId), zap.Error(err))
		return
	}
	for k, v := range ret {
		if strings.Index(k, constant.InstLoginNodeKey) == 0 {
			pubKey := constant.BalanceNKey + "." + v
			_ = gloader.CommMgr().NatsC().Publish(pubKey, b)
		}
	}
}
